package com.wk.code.wkserver.utils;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

/**
 * @author wq
 * @date 2020-06-22
 */
@SuppressWarnings("ALL")
public class DateUtils {


    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * 获取当前Date型日期
     *
     * @return Date() 当前日期
     */
    public static Date getNowDate() {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     *
     * @return String
     */
    public static String getDate() {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static String getTime() {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static String dateTimeNow() {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static String dateTimeNow(final String format) {
        return parseDateToStr(format, new Date());
    }

    public static String dateTime(final Date date) {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }


    /**
     * 获取时间戳
     *
     * @param date 时间
     * @return String
     * @throws ParseException
     */
    private static String getTimeStamp(Date date) throws ParseException {
        SimpleDateFormat f = new SimpleDateFormat("yyyyMMddHHmmss");
        return f.format(date);
    }

    public static Date dateTime(final String format, final String ts) {
        try {
            return new SimpleDateFormat(format).parse(ts);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }


    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * 比较时间大小
     *
     * @param beginTime 开始时间
     * @param now       当前时间
     * @return boolean
     * @throws ParseException
     */
    public static boolean comparetoTime(String beginTime, String now) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date bt = sdf.parse(beginTime);
        Date et = sdf.parse(now);
        if (bt.before(et)) {
            //表示bt小于et
            return true;
        } else {
            //--反之
            return beginTime.equals(now);
        }
    }

    /**
     * 解析时间
     *
     * @param time 时间字符串
     * @return 日期
     */
    public static Date parseDate(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return format.parse(time);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 解析时间
     *
     * @param time 时间字符串
     * @return 日期
     */
    public static Date parseDateTime(String time) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return format.parse(time);
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 添加天数
     *
     * @param startDate 开始时间
     * @param days      天数
     * @return Date
     */
    public static Date addDays(Date startDate, Integer days) {
        Calendar instance = Calendar.getInstance();
        instance.setTime(startDate);
        instance.add(Calendar.DAY_OF_MONTH, days);
        return instance.getTime();
    }

    /**
     * 获取相邻时间差
     *
     * @param day
     * @return
     */
    public static String getTimeSub(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, day);
        Date calendarTime = calendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(calendarTime);
    }


    /**
     * 添加天数
     *
     * @param startDate 开始时间
     * @param second    秒数
     * @return Date
     */
    public static Date subSecond(Date startDate, Integer second) {
        long sec = startDate.getTime() / 1000 - second;
        return new Date(sec * 1000);
    }

    /**
     * 格式化时间
     *
     * @param date 日期
     * @return 格式化的时间
     */
    public static String formatDateTime(Date date) {
        if (date == null) {
            return "-";
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(date);
    }

    /**
     * 格式化时间
     *
     * @param date 日期
     * @return 格式化的时间
     */
    public static String formatDate(Date date) {
        if (date == null) {
            return "-";
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(date);
    }

    /**
     * 格式化时间
     *
     * @param date 日期
     * @return 格式化的时间
     */
    public static String formatTime(Date date) {
        if (date == null) {
            return "-";
        }
        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
        return format.format(date);
    }

    /**
     * 过去最近七天的数据
     *
     * @return List<String>
     */
    public static List<String> getSevenDate() {
        List<String> dateList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");
        for (int i = 0; i < 7; i++) {
            Date date = org.apache.commons.lang3.time.DateUtils.addDays(new Date(), -i);
            String formatDate = sdf.format(date);
            dateList.add(formatDate);
        }
        Collections.reverse(dateList);
        return dateList;
    }


    /**
     * date 转 LocalDateTime
     *
     * @param date date
     * @return LocalDateTime
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
        return instant.atZone(zoneId).toLocalDateTime();
    }


    /**
     * LocalDateTime转换成Date
     *
     * @param date date
     * @return LocalDateTime
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        Date date = Date.from(zdt.toInstant());
        return date;
    }

    /**
     * 时间格式化
     *
     * @param localDateTime localDateTime
     * @return String
     */
    public static String localDate2Time(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        Date date = Date.from(zdt.toInstant());
        return formatDateTime(date);
    }


    /**
     * 计算时间差问题
     *
     * @param firstLoginTime 计算的时间
     * @param nowTime        时间
     * @return 时间差
     */
    public static String getDistanceTime(Date firstLoginTime, Date nowTime) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d1;
        Long days = null;
        Long hours = null;
        try {
            d1 = df.parse(df.format(nowTime));
            // 用户初次登录时间
            Date d2 = df.parse(df.format(firstLoginTime));
            // 当前的时间减去我初次登陆的时间如果大于等于2小时
            long diff = d1.getTime() - d2.getTime();
            // 共计秒数
            long seconds = diff / (1000);
            days = diff / (1000 * 60 * 60 * 24);
            hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
            long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60);
            if (days != 0) {
                if (days > 3) {
                    return "3天前";
                }
                return days.toString() + "天前";
            }
            if (hours != 0) {
                return hours.toString() + "小时前";
            }
            if (minutes != 0 && minutes > 30) {
                return "半小时前";
            }
            if (minutes != 0 && minutes < 30) {
                if (minutes <= 1) {
                    return "刚刚";
                }
                return minutes + "分钟前";
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return "刚刚";
    }

    /**
     * 获取一个随机时间
     *
     * @return Date
     */
    public static Date randDate() {
        Random r = new Random();
        String year = "2020";
        Integer month = r.nextInt(6) + 1;
        Integer day = r.nextInt(28) + 1;
        Integer hour = r.nextInt(24) + 1;
        Integer minute = r.nextInt(60) + 1;
        Integer sec = r.nextInt(60) + 1;
        String date = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + sec;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return simpleDateFormat.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return new Date();
        }
    }

    /**
     * 日期转为数字
     *
     * @param date 日期
     * @return 日期
     */
    public static Integer formatIntegerDate(Date date) {
        if (date == null) {
            return 0;
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        return Integer.parseInt(format.format(date));
    }

    /**
     * 格式化时间
     *
     * @param date 日期
     * @return MMdd HH:mm
     */
    public static String formatSimpleDateTime(Date date) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat format = new SimpleDateFormat("MM.dd HH:mm");
        return format.format(date);
    }

    /**
     * 获取 默认的时间
     *
     * @return DATE
     */
    public static Date defaultDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, 2000);
        calendar.set(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    /**
     * 计算星座
     *
     * @param birth 日期
     * @return 星座
     */
    public static String getConstellation(Date birth) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(birth);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        String constellation = "";
        if (month == 1 && day >= 20 || month == 2 && day <= 18) {
            constellation = "水瓶座";
        }
        if (month == 2 && day >= 19 || month == 3 && day <= 20) {
            constellation = "双鱼座";
        }
        if (month == 3 && day >= 21 || month == 4 && day <= 19) {
            constellation = "白羊座";
        }
        if (month == 4 && day >= 20 || month == 5 && day <= 20) {
            constellation = "金牛座";
        }
        if (month == 5 && day >= 21 || month == 6 && day <= 21) {
            constellation = "双子座";
        }
        if (month == 6 && day >= 22 || month == 7 && day <= 22) {
            constellation = "巨蟹座";
        }
        if (month == 7 && day >= 23 || month == 8 && day <= 22) {
            constellation = "狮子座";
        }
        if (month == 8 && day >= 23 || month == 9 && day <= 22) {
            constellation = "处女座";
        }
        if (month == 9 && day >= 23 || month == 10 && day <= 23) {
            constellation = "天秤座";
        }
        if (month == 10 && day >= 24 || month == 11 && day <= 22) {
            constellation = "天蝎座";
        }
        if (month == 11 && day >= 23 || month == 12 && day <= 21) {
            constellation = "射手座";
        }
        if (month == 12 && day >= 22 || month == 1 && day <= 19) {
            constellation = "摩羯座";
        }
        return constellation;
    }

    /**
     * 年龄的简称
     *
     * @param date 日期
     * @return age
     */
    public static String calAge(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = calendar.get(Calendar.YEAR);
        int s = year % 100;
        int m = s % 10;
        int n = s / 10;
        if (m < 5) {
            m = 0;
        } else {
            m = 5;
        }
        return "" + n + m + "后";
    }


    /**
     * 根据传入的天数来获取对应的日期
     *
     * @param days 代表天数  正数:为当前日期之后的,负数为当前日期之前
     * @return time
     */
    public static Date getDate(Integer days) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, days);
        Date time = cal.getTime();
        return time;
    }

    /**
     * 动态列表时间返回格式
     *
     * @param createTime 动态创建时间
     * @param date       当前时间
     * @return string
     */
    public static String getCommentTime(Date createTime, Date date) {
        //今天得评论时间
        if (getTimeYearMonthDate(createTime).equals(getTimeYearMonthDate(date))) {
            return getTime(createTime);
        } else if (getYesterDayTime(date).equals(getTimeYearMonthDate(createTime))) {
            return "昨天 " + getTime(createTime);
        } else if (getBeforeYesterDayTime(date).equals(getTimeYearMonthDate(createTime))) {
            return "前天 " + getTime(createTime);
        } else {
            //获取时间 月份日期以及时间
            return getMonthDateTime(createTime);
        }
    }

    /**
     * 获取昨天的日期
     *
     * @param date date
     * @return string
     */
    private static String getYesterDayTime(Date date) {
        long l = date.getTime() - 1000 * 60 * 60 * 24;
        Date date1 = new Date(l);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String yesterday = simpleDateFormat.format(date1);
        return yesterday;
    }

    private static String getBeforeYesterDayTime(Date date) {
        long l = date.getTime() - 1000 * 60 * 60 * 24 - 1000 * 60 * 60 * 24;
        Date date1 = new Date(l);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String beforeYesterday = simpleDateFormat.format(date1);
        return beforeYesterday;
    }


    /**
     * 获取日期
     *
     * @param date date
     * @return string
     */
    private static String getTimeYearMonthDate(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(date);
    }

    /**
     * 获取时间
     *
     * @param date date
     * @return string
     */
    private static String getTime(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
        return format.format(date);
    }

    private static String getMonthDateTime(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm");
        return format.format(date);
    }

    /**
     * 动态时间流
     *
     * @param createTime 创建时间
     * @param date       时间
     * @return string
     */
    public static String getDynamicTimeFeed(Date createTime, Date date) {
        //如果小于五分钟 则显示刚刚
        if (getTimeYearMonthDate(createTime).equals(getTimeYearMonthDate(new Date()))) {
            //当天时间
            if (Integer.parseInt(getCurrentTime(createTime)) >= Integer.parseInt(getFiveMinutesTime(date))) {
                return "刚刚";
            } else if (Integer.parseInt(getCurrentTime(createTime)) >= Integer.parseInt(getSixthMinutesTime(date)) &&
                    Integer.parseInt(getCurrentTime(createTime)) < Integer.parseInt(getFiveMinutesTime(date))) {
                return "五分钟前";
            } else {
                return getTime(createTime);
            }
        } else if (getYesterDayTime(date).equals(getTimeYearMonthDate(createTime))) {
            return "昨天 " + getTime(createTime);
        } else if (getBeforeYesterDayTime(date).equals(getTimeYearMonthDate(createTime))) {
            return "前天 " + getTime(createTime);
        } else {
            //获取时间 月份日期以及时间
            return "3天前";
        }
    }

    /**
     * 获取五分钟后的时间
     *
     * @param date date
     * @return string
     */
    public static String getFiveMinutesTime(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
        Date afterDate = new Date(date.getTime() - 300000);
        return sdf.format(afterDate);
    }


    /**
     * 获取1小时前的时间
     *
     * @param date date
     * @return string
     */
    public static String getSixthMinutesTime(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
        Date afterDate = new Date(new Date().getTime() - 300000 * 12);
        return sdf.format(afterDate);
    }


    /**
     * 当前时间
     *
     * @param date date
     * @return string
     */
    public static String getCurrentTime(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
        return sdf.format(date);
    }

    /**
     * 获取时间
     *
     * @param date 时间
     * @return String
     */
    public static String getCurrentDayTime(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    /**
     * 随机推荐时间
     *
     * @return 时间
     */
    public static String getRecommendTime() {
        List<String> list = Arrays.asList("1秒前推荐", "2秒前推荐", "3秒前推荐", "5秒前推荐", "10秒前推荐", "1分钟前推荐", "2分钟前推荐", "5分钟前推荐", "半小时前推荐");
        Random random = new Random();
        int n = random.nextInt(list.size());
        return list.get(n);
    }


    public static String secToTime(int time) {
        String timeStr = null;
        int hour = 0;
        int minute = 0;
        int second = 0;
        if (time <= 0)
            return "00:00";
        else {
            minute = time / 60;
            if (minute < 60) {
                second = time % 60;
                timeStr = unitFormat(minute) + ":" + unitFormat(second);
            } else {
                hour = minute / 60;
                if (hour > 99)
                    return "99:59:59";
                minute = minute % 60;
                second = time - hour * 3600 - minute * 60;
                timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second);
            }
        }
        return timeStr;
    }

    public static String unitFormat(int i) {
        String retStr = null;
        if (i >= 0 && i < 10)
            retStr = "0" + Integer.toString(i);
        else
            retStr = "" + i;
        return retStr;
    }


    public static Long getSecondsNextEarlyMorning() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
    }

    /**
     * 日期格式化
     *
     * @param localDateTime localDateTime
     * @return String
     */
    public static String localDateTime2DateStr(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        Date date = Date.from(zdt.toInstant());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd");
        return simpleDateFormat.format(date);
    }

    /**
     * 日期格式化
     *
     * @param localDateTime localDateTime
     * @return String
     */
    public static String localDateTime2DateStr(String format, LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);
        Date date = Date.from(zdt.toInstant());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(date);
    }
}
